#include <cstring>
#include <stdio.h>
#include <conio.h>
#include <iostream>
using namespace std;

/*
编译器并不是把函数模板处理成能够处理任意类的函数； 
编译器从函数模板通过具体类型产生不同的函数； 
编译器会对函数模板进行两次编译： 
在声明的地方对模板代码本身进行编译， 
在调用的地方对参数替换后的代码进行编译。
*/
namespace TempTrick {

// 模板特化  ,C++中的模板特化不同于模板的实例化，模板参数在某种特定类型下的具体实现称为模板的特化。模板特化有时也称之为模板的具体化，分别有函数模板特化和类模板特化。
    template<typename T>
    class A {
        T num;
    public:
        A() {
            num = T(6.6);
        }
        void print() {
            cout << "A'num:" << num << endl;
        }
    };

    template<>class A<char*> {
        char* str;
    public:
        A() {
            str = "A' special definition ";
        }
        void print() {
            cout << str << endl;
        }
    };

    void demo3() {
        A<int> a1; //显示模板实参的隐式实例化
        a1.print();
        A<char*> a2;//使用特化的类模板
        a2.print();
    }

    template<typename T> 
    T Max(T t1, T t2) {
        return (t1 > t2) ? t1 : t2;
    }

    typedef const char* CCP;
    template<> 
    CCP Max<CCP>(CCP s1, CCP s2) {
        return (strcmp(s1, s2) > 0) ? s1 : s2;
    }
    void demo2() {
        //调用实例：int Max<int>(int,int)
        int i = Max(10, 5);
        //调用显示特化：const char* Max<const char*>(const char*,const char*)
        const char* p = Max<const char*>("very", "good");
        cout << "i:" << i << endl;
        cout << "p:" << p << endl;
    }

    template<typename T>
    class C
    {
    public:
        size_t operator()(const T& t) { return t*2; };//可以实现将对象当函数来使用
    };
    //这就是语法，因为T已经绑定了， 所以<>里面没内容了，这么理解很赞；
    template<>
    class C<int>
    {
    public:
        size_t operator()(const int& i) { return i; }
    };

    // 模板偏特化；
    template<typename T1, typename T2, typename T3>
    class  D
    {
    public:
        size_t operator()(const T1& t1, const T2& t2, const T3& t3) { return 0; };
    };
    template<typename T2, typename T3>
    class D<int, T2, T3>
    {
    public:
        size_t operator()(const int& t1, const T2& t2, const T3& t3) { return 0; };
    };

    template<typename T1, typename T3>
    class  D<T1, int, T3>
    {
    public:
        size_t operator()(const T1& t1, const int& t2, const T3& t3) { return 0; };
    };

    /*
    * 模板偏特化:指针；
    * e针对T为T*的类型进行偏特化
    */
    template <typename T>
    class E
    {
    public:    void info() {
            cout << " class E  \t-->common\n";
        }
    };

    template <typename T>
    class E<T*>
    {
    public:  void info() {
            cout << " class E  \t--> point\n";
        }
    };

    void demo1()
    {
        float v1 = 10;
        int v2 = 20;

        C<int> c1;
        cout << "C<int>  c1   \t" << c1(v1) << endl;
        C<float> c2;
        cout << "C<float>  c2   \t" << c2(v1) << endl;

        E<float> e1;
        E<int*> e2;
        e1.info();
        e2.info();
    }
    

    //以指针为模板参数
    template<int* p >
    struct wrapper
    {
        /* data */
        int get() { return *p; }
        void set(int v) { *p = v; }
    };


    //以引用为模板参数
    template<int& p>
    struct wrapper1
    {
        /* data */
        int get() { return p; }
        void set(int v) { p = v; }
    };

    int global_var = 0;
    void demo()
    {
        wrapper<&global_var>gwrapper;
        gwrapper.set(1);
        cout << gwrapper.get() << endl;

        wrapper1<global_var>gwrapper1;
        gwrapper1.set(2);
        cout << gwrapper1.get() << endl;
    }

/*
《Effective C++》的作者Scott Meyers所设计的。通过继承以下代码中的基类，所有的派生类便可实现类实例计数的功能。
在下面的基类中，将包含一个表示对象计数的静态成员，同时还会在基类构造的时候递增该值，并在析构的时候递减该值
*/
template<typename CountedType>
class ObjectCounter {
private:
    static size_t count;

protected:
    ObjectCounter() {
        ++ObjectCounter<CountedType>::count;
    }
    ObjectCounter(ObjectCounter<CountedType> const&) {
        ++ObjectCounter<CountedType>::count;
    }
    ~ObjectCounter() {
        --ObjectCounter<CountedType>::count;
    }

public:
    static size_t liveCount() {
        return ObjectCounter<CountedType>::count;
    }
};

template<typename CountedType>
size_t ObjectCounter<CountedType>::count = 0;

//C++编译器会根据模板参数的不同实例化不同类型的类对象，因此模板参数不同，所使用的静态成员也是不同的。
class MyClass : public ObjectCounter<MyClass> {
};
class MyClass1 : public ObjectCounter<MyClass1> {
};
int main() {
    demo1();
    demo();

    MyClass mc1;
    MyClass1 mc11;

    printf("The count of MyClass is %lld \n", MyClass::liveCount());
    printf("The count of MyClass1 is %lld \n", MyClass1::liveCount());
    {
        MyClass mc2;
        printf("The count of MyClass is %lld \n", MyClass::liveCount());
    }
    printf("The count of MyClass is %lld \n", MyClass::liveCount());

    
    printf("The count of MyClass is %lld \n", MyClass::liveCount());
    printf("The count of MyClass1 is %lld \n", MyClass1::liveCount());
    return 0;
}
//The count of MyClass is 1
//The count of MyClass is 2
//The count of MyClass is 1
}
